﻿using System;
using SdmxMl.Common;
using SdmxMl.Manager;
using SdmxMl.Structure;
using Ch.Admin.Bfs.Sms.Sdmx.Extension.CodeBook.Configuration;

namespace Ch.Admin.Bfs.Sms.Sdmx.Extension.CodeBook.Meta
{
    public class HierarchyCodelistProvider : BaseMetaProvider, IMetaProvider
    {        
        private HierarchicalCodelistType hcl;

        public HierarchyCodelistProvider(string lang, string hcFullId, BookConfiguration cfg) : base(lang, hcFullId, cfg)
        {
            try
            {
                // Get required maintenable artefact
                ArtefactRefTyped art = new ArtefactRefTyped(SdmxArtefactType.HierarchicalCodelists, fullIdKey);
                sm.LoadMissingArtefactsFromRegistry(art);
                hcl = sm.GetArtefact(art) as HierarchicalCodelistType;

                ProduceHierarchy();
            }
            catch (Exception ex)
            {
                throw new ApplicationException("Unable to obtain related metadata for " + fullIdKey, ex);
            }
        }

        private void ProduceHierarchy()
        {
            hierarchy = new Hierarchy();
            hierarchy.Add(new HierarchyNode(hcl.Id, hcl.Name.GetForLanguage(lg), hcl.Description.GetForLanguage(lg), hcl));
            // each hierarchy
            foreach (HierarchyType h in hcl.HierarchyList)
            {
                HierarchyNode subNode = new HierarchyNode(h.Id, h.Name.GetForLanguage(lg), h.Description.GetForLanguage(lg), h);
                hierarchy[0].Nodes.Add(subNode);
                FillRecurse(subNode.Nodes, h.CodeRefList);
            }
        }

        private void FillRecurse(Hierarchy nodes, CodeRefTypeList listItems)
        {
            foreach (CodeRefType c in listItems)
            {
                CodeListType clt = GetCodelist(c.CodelistAliasRef);
                if (dicoCodelist.ContainsKey(clt.FullIdent) == false)
                    dicoCodelist.Add(clt.FullIdent, clt);

                HierarchyNode childNode = new HierarchyNode(c.CodeID, clt.CodeList.LocateItem(c.CodeID).Name.GetForLanguage(lg), c);
                nodes.Add(childNode);
                FillRecurse(childNode.Nodes, c.CodeRefList);
            }
        }

        private CodeListType GetCodelist(string alias)
        {
            CodeListType clt = null;
            foreach (CodelistRefType crt in hcl.CodelistRefList)
            {
                if (crt.Alias == alias)
                {
                    clt = refHelper.GetCodelist(crt);
                    break;
                }
            }
            return clt;
        }
    }
}
